import time
import traceback
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import logging
formatter = '%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s'
# 使用FileHandler输出到文件
fh = logging.FileHandler('auto_radiocaca.log')
fh.setLevel(logging.INFO)
fh.setFormatter(formatter)

# 使用StreamHandler输出到屏幕
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(formatter)

# 添加两个Handler
logger = logging.getLogger()
logger.addHandler(ch)
logger.addHandler(fh)
# logging.basicConfig(level=logging.INFO, filename="auto_radiocaca.log", filemode="a",
#                     format=formatter)
from websocket_client import *
import yaml


class OperateProcess(object):
    def __init__(self):
        self.mutex = threading.Lock()
        self.config = {}
        with open("operate_process.yaml", "rb") as f:
            self.config = yaml.safe_load(f)
        logging.info(self.config)
        self.ws_client = WebsocketClient(self, url=self.config["ws_server_url"])

        self.all_data = {}

    def run(self):  # 固定用run方法，启动进程自动调用run方法
        self.ws_client.start()
        self.init_chrome()
        self.login_metamask()
        self.loop_execute()

    def init_chrome(self):
        logging.info("初始化浏览器")
        option = webdriver.ChromeOptions()
        option.add_argument("user-data-dir=" + self.config["chrome_user_data"])
        option.add_argument('--no-sandbox')
        option.add_argument('--disable-dev-shm-usage')
        if self.config["chrome_use_headless"]:
            option.add_argument("headless")
        option.add_argument('ignore-certificate-errors')
        option.add_argument('log-level=3')
        option.add_argument('lang=zh_CN.UTF-8')
        prefs = {
            'profile.default_content_setting_values': {
                'images': 1,
                'stylesheet': 2,
            }
        }
        option.add_experimental_option('prefs', prefs)
        self.chrome = webdriver.Chrome(executable_path=self.config["chrome_dirver_path"], chrome_options=option)
        self.chrome.maximize_window()

    def switch_window_to_url(self, url, count=1):
        while count > 0:
            for window_handle in self.chrome.window_handles:
                self.chrome.switch_to.window(window_handle)
                logging.debug(self.chrome.current_url)
                if url in self.chrome.current_url:
                    return True
            time.sleep(0.5)
            count -= 1
        return False

    def login_metamask(self):
        logging.info("登录钱包")
        self.chrome.get(self.config["url_market_place"])
        self.checkPage()
        try:
            if self.switch_window_to_url(self.config["url_metamask_unlock"]):
                ret = self.chrome.find_elements_by_xpath(self.config["xpath_password"])
                if len(ret) > 0:
                    pass_input = ret[0]
                    pass_input.send_keys(self.config["metamask_password"])
                    time.sleep(2)
                    unlock_btn = self.chrome.find_element_by_xpath(self.config["xpath_unlock"])
                    unlock_btn.click()
        except:
            traceback.print_exc()

    def loop_execute(self):
        logging.info("开始购买")
        while True:
            m_id, buy_now_item = self.get_buy_now()
            if m_id:
                s_id = str(m_id)
                logging.info("购买产品信息：" + s_id + ", " + str(buy_now_item))
                url = self.config["url_market_place"] + s_id
                js = 'window.open("' + url + '")'
                self.chrome.execute_script(js)
                logging.info("[" + s_id + "] " + "打开产品页面: " + url)
                self.checkPage()
                self.switch_window_to_url(url)

                # 获取buy now按钮
                logging.info("获取buy now按钮")
                WebDriverWait(self.chrome, 5, 0.5).until(EC.presence_of_element_located((
                    By.XPATH, self.config["xpath_buy1"])))
                buy_btn = self.chrome.find_element_by_xpath(self.config["xpath_buy1"])
                self.chrome.execute_script("arguments[0].click()", buy_btn)
                logging.info("[" + s_id + "] " + "点击购买")

                # 获取approve按钮
                logging.info("获取approve按钮")
                WebDriverWait(self.chrome, 5, 0.5).until(EC.presence_of_element_located((
                    By.XPATH, self.config["xpath_approve"])))
                approve_btn = self.chrome.find_element_by_xpath(self.config["xpath_approve"])
                self.chrome.execute_script("arguments[0].click()", approve_btn)
                logging.info("[" + s_id + "] " + "点击授权")

                # 钱包授权
                logging.info("钱包授权")
                approve_flag = False
                if self.switch_window_to_url(self.config["url_metamask_approve"], 5):
                    next_btn = self.chrome.find_element_by_xpath(self.config["xpath_comfirm"])
                    cancel_btn = self.chrome.find_element_by_xpath(self.config["xpath_cancel"])
                    if logging.info(next_btn.get_attribute("disabled")):
                        self.chrome.execute_script("arguments[0].click()", next_btn)
                        logging.info("[" + s_id + "] " + "钱包授权成功")
                        approve_flag = True
                    else:
                        logging.warning("[" + s_id + "] " + "余额不足，点击拒绝")
                        self.chrome.execute_script("arguments[0].click()", cancel_btn)

                # 切换到产品页面
                logging.info("切换到产品页面")
                self.switch_window_to_url(url)
                # 判断授权是否成功
                logging.info("判断授权是否成功")
                if approve_flag:
                    buy_btn = self.chrome.find_element_by_xpath(self.config["xpath_buy2"])
                    self.chrome.execute_script("arguments[0].click()", buy_btn)
                    logging.info("购买成功")
                    time.sleep(1)
            time.sleep(0.2)

    def checkPage(self):
        checkPageFinishScript = "try {if (document.readyState !== 'complete') {return false;} if (window.jQuery) { if (" \
                                "window.jQuery.active) { return false; } else if (window.jQuery.ajax && " \
                                "window.jQuery.ajax.active) { return false; } } if (window.angular) { if (!window.qa) { " \
                                "window.qa = {doneRendering: false }; } var injector = window.angular.element(" \
                                "'body').injector(); var $rootScope = injector.get('$rootScope'); var $http = " \
                                "injector.get('$http'); var $timeout = injector.get('$timeout'); if ($rootScope.$$phase " \
                                "=== '$apply' || $rootScope.$$phase === '$digest' || $http.pendingRequests.length !== 0) " \
                                "{ window.qa.doneRendering = false; return false; } if (!window.qa.doneRendering) { " \
                                "$timeout(function() { window.qa.doneRendering = true;}, 0); return false;}} return " \
                                "true;} catch (ex) {return false;} "
        return self.chrome.execute_script(checkPageFinishScript)

    def buy_now(self, msg):
        logging.info("buy_now")
        self.mutex.acquire()
        self.all_data["buy_now"] = msg
        self.mutex.release()

    def get_buy_now(self):
        m_id = None
        item = None
        self.mutex.acquire()
        if "buy_now" in self.all_data:
            for key, data in self.all_data["buy_now"] .items():
                m_id = key
                item = data
                break
        self.mutex.release()
        return m_id, item

    def price_limit(self, msg):
        logging.info("price_limit")
        self.mutex.acquire()
        self.all_data["price_limit"] = msg
        self.mutex.release()


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    operate_process = OperateProcess()
    operate_process.run()
